package service

import (
	"GopherFocus/app/model"
	"GopherFocus/app/shared"
	"context"
)

var Session = sessionService{}

type sessionService struct{}

const (
	sessionKeyUser    = "SessionKeyUser"    // 用户信息存放在session中的key
	sessionKeyNotice  = "SessionKeyNotice"  // 提示信息存放在session中的key
	sessionKeyReferer = "SessionKeyReferer" // Referer存储，当已存在该Referer时不会更新，用于用户未登录时引导用户登录，或者重定向
)

// 删除用户Session
func (s *sessionService) RemoveUser(ctx context.Context) error {
	customCtx := shared.Context.Get(ctx)
	if customCtx != nil {
		return customCtx.Session.Remove(sessionKeyUser)
	}
	return nil
}

// 设置用户session
func (s *sessionService) SetUser(ctx context.Context, user *model.User) error {
	return shared.Context.Get(ctx).Session.Set(sessionKeyUser, user)
}

// 获取用户session
func (s *sessionService) GetUser(ctx context.Context) *model.User {
	customCtx := shared.Context.Get(ctx)
	// 对可能返回为nil的情况都需要进行判断，增加健壮性
	// 虽然在middleware中初试化了customCtx，但是为了避免在其他地方错误调用GetUser，还是需要对nil进行判断
	if customCtx != nil {
		v := customCtx.Session.GetVar(sessionKeyUser)
		// session中的用户是否为nil，为nil则表示未登录，直接返回nil
		if !v.IsNil() {
			var user *model.User
			// 将v的值映射到user
			_ = v.Struct(&user)
			return user
		}
	}
	return nil
}

// 设置notice信息
func (s *sessionService) SetNotice(ctx context.Context, notice *model.SessionNotice) error {
	// 第一步都是根据ctx获取到customCtx
	customCtx := shared.Context.Get(ctx)
	if customCtx != nil {
		return customCtx.Session.Set(sessionKeyNotice, notice)
	}
	return nil
}

// 获取notice信息
func (s *sessionService) GetNotice(ctx context.Context) (*model.SessionNotice, error) {
	customCtx := shared.Context.Get(ctx)
	// 判断customCtx是否为nil
	if customCtx != nil {
		// GetVar返回*gvar.Var类型，可以使用Struct方法转换为指定类型结构体
		// 而Get方法返回一个interface，转换较麻烦，所以使用GetVar更好
		var notice *model.SessionNotice
		err := customCtx.Session.GetVar(sessionKeyNotice).Struct(&notice)
		return notice, err
	}
	return nil, nil
}

// 删除notice信息
func (s *sessionService) RemoveNotice(ctx context.Context) error {
	customCtx := shared.Context.Get(ctx)
	if customCtx != nil {
		return customCtx.Session.Remove(sessionKeyNotice)
	}
	return nil
}

// 获取LoginReferer
func (s *sessionService) GetLoginReferer(ctx context.Context) string {
	customCtx := shared.Context.Get(ctx)
	if customCtx != nil {
		return customCtx.Session.GetString(sessionKeyReferer)
	}
	return ""
}

// 设置LoginReferer，如果已存在则不设置
func (s *sessionService) SetLoginReferer(ctx context.Context, referer string) error {
	if s.GetLoginReferer(ctx) == "" {
		customCtx := shared.Context.Get(ctx)
		if customCtx != nil {
			return customCtx.Session.Set(sessionKeyReferer, referer)
		}
	}
	return nil
}

// 删除LoginReferer
func (s *sessionService) RemoveLoginReferer(ctx context.Context) error {
	customCtx := shared.Context.Get(ctx)
	if customCtx != nil {
		return customCtx.Session.Remove(sessionKeyReferer)
	}
	return nil
}
